/*-
 * Copyright (c) 2007-2008 SINA Corporation, All Rights Reserved.
 * Author: Zhang shuo <zhangshuo@staff.sina.com.cn>
 * A http protocol implement under Zhu Yan's SASE(csf) framework.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <stdio.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>

#include "libmod.h"
#include "log.h"
#include "confparser.h"
#include "queue.h"
#include "http.h"

#define MAX_UPLOAD_DIR_LENGTH   256

int mod_init(char *);
static int write_file(const char *filename, struct iovec *iov, int n_iov);

char UPLOAD_DIR[MAX_UPLOAD_DIR_LENGTH + 1];
static struct conf_str_config conf_str_array[] = {
	{"upload_dir", UPLOAD_DIR}, 
	{0, 0}
};

/* write file to disk through writev system call */
static int
write_file(const char *filename, struct iovec *iov, int n_iov)
{
	int fd;
	int retval;

	fd = open(filename, O_WRONLY | O_CREAT);
	
	if (fd < 0) {
		WLOG_ERR("fd: %d, i: %d, err: %s\n", fd, n_iov, strerror(errno));
		return (-1);
	}

	retval = writev(fd, iov, n_iov);
	
	if (retval < 0) {
		WLOG_ERR("fd: %d, i: %d, err: %s\n", fd, n_iov, strerror(errno));
		close(fd);
		return (-1);
	}

	WLOG_DEBUG("Create file OK!");
	close(fd);
	return 0;
}


static ssize_t 
socket_handler(WTI *wtip, CONN_INFO *cip, void *data, void **res)
{
    struct iovec upload_patch_arr[MAX_PATCH_NUMBER];
    UPLOAD_PATCH *upload_patch;
    ssize_t iovcnt = 0;
    
    struct tm *tm_ptr;
    time_t the_time;
    char file_path[256];

    CSF_UNUSED_ARG(res);
    CSF_UNUSED_ARG(cip);
    CSF_UNUSED_ARG(wtip);
    
    STQ_HEAD *tailq_head = (STQ_HEAD *)data;

    /* create an array iov for struct iovec */
    STAILQ_FOREACH(upload_patch, tailq_head, entries)
    {
        upload_patch_arr[iovcnt].iov_base = upload_patch->buf;
        upload_patch_arr[iovcnt].iov_len = upload_patch->len;

        iovcnt++;
        
        if (iovcnt > MAX_PATCH_NUMBER)
        {
            WLOG_ERR("[http]writev over limit(iovcnt) when upload.");
            return (PIPELINE_FAILED);
        }
    }
    
    #ifdef UPLOAD_DEBUG
    printf("ivo is %ld\n", iovcnt);
    #endif
    
    /* gernerate file path */
    memset(file_path, '\0', sizeof(file_path));
        
    /* get host time */
    time(&the_time);
    tm_ptr = gmtime(&the_time);
    snprintf(file_path, sizeof(file_path)-1, 
                "%s/upload%d%d%d%d%d%d.data", 
                UPLOAD_DIR, tm_ptr->tm_year + 1900, 
                tm_ptr->tm_mon+1, tm_ptr->tm_mday, tm_ptr->tm_hour, 
                tm_ptr->tm_min, tm_ptr->tm_sec);
    
    if (write_file(file_path, upload_patch_arr, iovcnt) == -1)
    {
        WLOG_ERR("[http]write to disk error when upload. %s", strerror(errno));
    }

    return (PIPELINE_CONTINUE);
}


static ssize_t
http_init(void *arg, void **res)
{
	char mod_name[] = "http_upload.so";
	int r;
	CSF_UNUSED_ARG(arg);
	CSF_UNUSED_ARG(res);
	
	r = load_conf(NULL, mod_name, NULL, conf_str_array);
	
	if (r != 0)
		WLOG_ERR("http_init load_conf() failed!");	
		
    return 0;
}


int 
mod_init(char *mod_name)
{
	CSF_UNUSED_ARG(mod_name);
	
	set_request_init(http_init);
	set_request_deinit(NULL);
	set_request_handler(socket_handler);

	return (0);
}





